#pragma once
/*
 *  SBJ/NXT/CommandTraits.h
 *  NXTFace
 *
 *  Created by David Giovannini on 8/23/06.
 *  Copyright 2006 Software by Jove. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 */

#include "SBJ/NXT/Enums.h"
#include "SBJ/NXT/Types.h"

#include <string>

namespace SBJ
{

namespace NXT
{

// Very important, we want fully packed structs
#pragma pack(1)

struct StartProgram
{
	enum { code = 0x00 };
	typedef String< 20 > Params;
	typedef Empty Results;
};

struct StopProgram
{
	enum { code = 0x01 };
	typedef Empty Params;
	typedef Empty Results;
};

struct GetProgramName
{
	enum { code = 0x11 };
	typedef Empty Params;
	typedef String< 20 > Results;
};

struct KeepAlive
{
	enum { code = 0x0D };
	typedef Empty Params;
	typedef Int< UBytes4 > Results;
};

struct PlaySound
{
	enum { code = 0x02 };
	struct Params
	{
		Bool loop;
		String< 20 > name;
	};
	typedef Empty Results;
};

struct StopSound
{
	enum { code = 0x0C };
	typedef Empty Params;
	typedef Empty Results;
};

struct PlayTone
{
	enum { code = 0x03 };
	struct Params
	{
		IntRange< UBytes2, 200, 14000 > hrz;
		Int< UBytes2 > ms;
	};
	typedef Empty Results;
};

struct GetInput
{
	enum { code = 0x07 };
	typedef Enum< InputPort > Params;
	struct Results
	{
		Enum< InputPort > port;
		Bool valid;
		Bool calibrated;
		Enum< SensorType > type;
		Enum< SensorMode > mode;
		Int< UBytes2 > rawValue;
		IntRange< UBytes2, 0, 1023  > normValue;
		Int< SBytes2 > scaledValue;
		Int< SBytes2 > calibratedValue;
	};
};

struct SetInput
{
	enum { code = 0x05 };
	struct Params
	{
		Params( const GetInput::Results& result )
		: port( result.port )
		, type( result.type )
		, mode( result.mode )
		{
		}
		
		Enum< InputPort > port;
		Enum< SensorType > type;
		Enum< SensorMode > mode;
	};
	typedef Empty Results;
};

struct ResetInputScaledValue
{
	enum { code = 0x08 };
	typedef Enum< InputPort > Params;
	typedef Empty Results;
};

struct GetOutput
{
	enum { code = 0x06 };
	typedef Int< UBytes1 > Params;

	struct Results
	{
		Enum< OutputPort > port;
		IntRange< SBytes1, -100, 100 > power;
		Enum< MotorMode > mode;
		Enum< Regulation > regulation;
		IntRange< SBytes1, -100, 100 > turn_ratio;
		Enum< MotorState > state;
		Int< UBytes4 > tacho_limit;
		Int< SBytes4 > tacho_count;
		Int< SBytes4 > block_tacho_count;
		Int< SBytes4 > rotation_tacho_count;
	};
};

struct SetOutput
{
	enum { code = 0x04 };
	struct Params
	{
		Enum< OutputPort > port;
		IntRange< SBytes1, -100, 100 > power;
		Enum< MotorMode > mode;
		Enum< Regulation > regulation;
		IntRange< SBytes1, -100, 100 > turn_ratio;
		Enum< MotorState > state;
		Int< UBytes4 > tacho_limit;
		
		Params( const GetOutput::Results& result )
		: port( result.port )
		, power( result.power )
		, mode( result.mode )
		, regulation( result.regulation )
		, turn_ratio( result.turn_ratio )
		, state( result.state )
		, tacho_limit( result.tacho_limit )
		{
		}
	};
	typedef Empty Results;
};

struct ResetMotorPosition
{
	enum { code = 0x0A };
	struct Params
	{
		Enum< OutputPort > port;
		Bool relative;
	};
	typedef Empty Results;
};

struct GetBatteryLevel
{
	enum { code = 0x0B };
	typedef Empty Params;
	typedef IntRange< UBytes2, 0, 10000 > Results;
};

struct WriteMessage
{
	enum { code = 0x09 };
	struct Params
	{
		IntRange< UBytes1, 0, 9, 0 > box;
		Message< 59, 3 > msg;
	};
	typedef Empty Results;
};

struct ReadMessage
{
	enum { code = 0x13 };
	struct Params
	{
		IntRange< UBytes1, 0, 19, 0 > remoteBox;
		IntRange< UBytes1, 0, 9, 0 > localBox;
		Bool clear;
	};
	struct Results
	{
		IntRange< UBytes1, 0, 9, 0 > box;
		Message< 59 > msg;
	};
};

#pragma pack()
}

}